home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / modules / nessus-2.2.8.mo / usr / lib / nessus / plugins / dns_xfer.nasl < prev    next >
Text File  |  2005-03-31  |  8KB  |  261 lines

  1. #
  2. #
  3. # This script was written by John Lampe <j_lampe@bellsouth.net>
  4. # Modified by Axel Nennker <axel@nennker.de>
  5. # Modified by Erik Anderson <eanders@pobox.com>
  6. # Modified by Pavel Kankovsky <kan@dcit.cz>
  7. #
  8. # See the Nessus Scripts License for details
  9. #
  10.  
  11. if(description)
  12. {
  13.  script_id(10595);
  14.  script_version ("$Revision: 1.15 $");
  15.  script_cve_id("CAN-1999-0532");
  16.  name["english"] = "DNS AXFR"; 
  17.  script_name(english:name["english"]);
  18.  
  19.  desc["english"] = "
  20. The remote name server allows DNS zone transfers to be performed.
  21. A zone transfer will allow the remote attacker to instantly populate
  22. a list of potential targets.  In addition, companies often use a naming
  23. convention which can give hints as to a servers primary application
  24. (for instance, proxy.company.com, payroll.company.com, b2b.company.com, etc.).
  25.  
  26. As such, this information is of great use to an attacker who may use it
  27. to gain information about the topology of your network and spot new
  28. targets.
  29.  
  30. Solution: Restrict DNS zone transfers to only the servers that absolutely
  31. need it.
  32.  
  33. Risk factor : Medium";
  34.  
  35.  
  36.  script_description(english:desc["english"]);
  37.  summary["english"] = "Determines if the remote name server allows zone transfers";
  38.  script_summary(english:summary["english"]);
  39.  
  40.  script_category(ACT_GATHER_INFO);
  41.  
  42.  script_copyright(english:"This script is Copyright (C) 2000 j_lampe@bellsouth.net");
  43.  family["english"] = "General";
  44.  script_family(english:family["english"]);
  45.  
  46.  # should require "Services/dns" but find_service.nes does not recognize dns
  47.  # mayby copy copy some code from here to find_service.nes???
  48.  # script_require_ports("Services/dns", 53);
  49.  script_require_ports(53);
  50.  # script_require_udp_ports(53);
  51.  exit(0);
  52. }
  53.  
  54. #start code
  55.  
  56. # debug_level
  57. include("global_settings.inc");
  58.  
  59. function myintstring_to_int (mychar) {
  60.         myintrray = "0123456789";
  61.         for (q=0; q<10; q=q+1) {
  62.                 if(myintrray[q] == mychar) return (q + 48);
  63.         }
  64. }
  65.  
  66. #create UDP DNS header
  67. get_host_by_addr = raw_string(0xB8, 0x4C, 0x01, 0x00, 0x00, 0x01,
  68.                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  69.  
  70. #Add in reversed octet order IP addr
  71.  
  72. myip = get_host_ip();
  73. len = strlen(myip);          
  74. counter=0;
  75. for (flag = len; flag > 0; flag = flag - 1) {
  76.   if (myip[flag-1] == ".")  {
  77.     get_host_by_addr = get_host_by_addr + raw_string(counter);
  78.     for (tcount = flag; tcount < flag + counter; tcount = tcount + 1) {
  79.       mcount = temprray[tcount];
  80.       get_host_by_addr = get_host_by_addr + raw_string(mcount);
  81.     }     
  82.     for (mu=0; mu<15; mu=mu+1) {temprray[mu]=0;}
  83.       counter = 0;
  84.   } else {
  85.     temprray[flag-1] = myintstring_to_int(mychar:myip[flag-1]);
  86.     counter = counter + 1;
  87.   }          
  88. }            
  89.  
  90. get_host_by_addr = get_host_by_addr + raw_string(counter);
  91. for (tcount=flag; tcount<flag + counter; tcount = tcount + 1) {
  92.   mcount = temprray[tcount];
  93.   get_host_by_addr = get_host_by_addr + raw_string(mcount);
  94. }
  95.  
  96. #add in in-addr.arpa
  97. get_host_by_addr = get_host_by_addr +  raw_string(0x07, 0x69, 0x6E, 0x2D, 0x61, 0x64,
  98.                                                   0x64, 0x72, 0x04, 0x61, 0x72, 0x70,
  99.                                                   0x61);
  100.  
  101.  
  102. get_host_by_addr = get_host_by_addr + raw_string(0x00, 0x00, 0x0C, 0x00, 0x01);
  103.  
  104. # fetch big-endian 16-bit value (string s, offset o)
  105. function ntohs(s, o) {
  106.   local_var ret_hi, ret_lo;
  107.   ret_hi = ord(s[o]) << 8;
  108.   ret_lo = ord(s[o+1]);
  109.   return (ret_hi + ret_lo);
  110. }
  111.  
  112. # skip one chain of labels
  113. # returns the new offset ("jump")
  114. function skiplabels(buf, buflen, jump) {
  115.   local_var curlabel;
  116.   while (jump < buflen) {
  117.     curlabel = ord(buf[jump]);
  118.     if (curlabel == 0) {
  119.       jump += 1;
  120.       return (jump);
  121.     }
  122.     if (curlabel >= 0xc0) {
  123.       jump += 2;
  124.       return (jump);
  125.     }
  126.     jump += curlabel + 1;
  127.   }
  128.  return jump;
  129. }
  130.  
  131. # fetch one chain of labels
  132. # returns the chain of labels (decompressed) or NULL if error
  133. # skips "skip" leading labels
  134. function fetchlabels(buf, buflen, jump, skip) {
  135.   local_var curlabel, result, iter;
  136.   iter = 10;
  137.   result = "";
  138.   while (jump < buflen && iter > 0) {
  139.     curlabel = ord(buf[jump]);
  140.     if (curlabel == 0) {
  141.       # that's all folks!
  142.       if (debug_level) {
  143.         display("debug: fetchlabels >>", result,
  144.                 "<< (len=", strlen(result), ")\n");
  145.       }
  146.       return (result);
  147.     }
  148.     else if (curlabel < 0xc0) {
  149.       # new label
  150.       if (jump + curlabel + 1 > buflen) return (NULL);
  151.       if (isnull(skip) || skip <= 0)
  152.         result = strcat(result, substr(buf, jump, jump + curlabel));
  153.       else
  154.         skip -= 1;
  155.       jump += curlabel + 1;
  156.     }
  157.     else {
  158.       # compressed indirect reference
  159.       iter -= 1; # prevent endless loop
  160.       if (jump + 2 > buflen) return (NULL);
  161.       jump = ntohs(s:buf, o:jump) & 0x3fff;
  162.     }
  163.   }
  164.   return (NULL);
  165. }
  166.  
  167. # send UDP PTR query
  168. soc = open_sock_udp(53);
  169. if (!soc) exit(0);
  170. send(socket:soc, data:get_host_by_addr);
  171. myreturn = recv(socket:soc, length:4096);
  172. myretlen = strlen(myreturn);
  173. if (debug_level)
  174.   display("debug: got UDP answer myretlen=", myretlen, "\n");
  175.  
  176. close(soc);
  177. if(myretlen < 12) exit(0);
  178.  
  179. # analyze UDP answer
  180. # maybe save this info to kb as "Port/udb/53=1" if (strlen(myreturn>0))
  181. ancount = ntohs(s:myreturn, o:6);
  182. if (ancount < 1) exit(0);
  183. # skip header and query section
  184. jump = 12;
  185. if (debug_level > 1)
  186.   fetchlabels(buf:myreturn, buflen:myretlen, jump:jump);
  187. jump = skiplabels(buf:myreturn, buflen:myretlen, jump:jump);
  188. jump += 4;
  189.  
  190. # walk through answers
  191. # we look for IN PTR
  192. found_answer = 0;
  193. for (theta = 0; (theta < ancount) && (jump < myretlen); theta += 1) {
  194.   if (debug_level > 1)
  195.     fetchlabels(buf:myreturn, buflen:myretlen, jump:jump);
  196.   jump = skiplabels(buf:myreturn, buflen:myretlen, jump:jump);
  197.   jump += 10;
  198.   if (jump < myretlen) {
  199.     rtype  = ntohs(s:myreturn, o:jump-10);
  200.     rclass = ntohs(s:myreturn, o:jump-8);
  201.     if (debug_level)
  202.       display("debug: UDP answer RR rtype=", rtype, " rclass=", rclass, "\n");
  203.     # check type 12 (PTR) & class 1 (IN)
  204.     # XXX we might get multiple PTR records
  205.     if (rtype == 12 && rclass == 1) {
  206.       found_answer = 1;
  207.       break;
  208.     }
  209.     jump += ntohs(s:myreturn, o:jump-2);
  210.   }
  211. }
  212.  
  213. if (!found_answer) exit(0);
  214. domain = fetchlabels(buf:myreturn, buflen:myretlen, jump:jump, skip:1);
  215. if (isnull(domain) || domain == "") exit(0);
  216.  
  217. #start putting together the TCP DNS zone transfer request
  218. pass_da_zone = strcat(
  219.   raw_string(0x68, 0xB3,   # ID
  220.              0x00, 0x00,   # QR|OC|AA|TC|RD|RA|Z|RCODE
  221.              0x00, 0x01,   # QDCOUNT
  222.              0x00, 0x00,   # ANCOUNT
  223.              0x00, 0x00,   # NSCOUNT
  224.              0x00, 0x00),  # ARCOUNT
  225.   domain,
  226.   raw_string(0x00,         # NULL Terminator
  227.              0x00, 0xFC,   # QTYPE=252=ZoneTransfer
  228.              0x00, 0x01)   # QCLASS=1=Internet
  229. );
  230.  
  231. len = strlen(pass_da_zone);
  232. len_hi = len / 256;
  233. len_lo = len % 256;
  234. pass_da_zone = raw_string(len_hi, len_lo) + pass_da_zone;
  235.  
  236. # send TCP AXFR query
  237. if (!get_port_state(53)) exit(0);
  238. soctcp = open_sock_tcp(53);
  239. if (!soctcp) exit(0);
  240. send(socket:soctcp, data:pass_da_zone);
  241. incoming = recv(socket:soctcp, length:2);
  242. if (strlen(incoming) < 2) exit(0);
  243. len = ntohs(s:incoming, o:0);
  244. if (debug_level)
  245.   display("debug: got TCP answer len=", len, "\n");
  246. # don't want an infinite loop, if answer is illegal
  247. if (len < 0) exit(0);
  248. # only interessted in incoming[7]
  249. if (len > 8) len = 8;
  250. incoming = recv(socket:soctcp, length:len, min: len);
  251. close(soctcp);
  252.  
  253. # analyze TCP answer
  254. ancount = ntohs(s:incoming, o:6);
  255. if (ancount >= 1) {
  256.   security_warning(53);
  257. }
  258.  
  259. exit(0);
  260.  
  261.